package com.katze.boot.plugins.redis.operations;

import com.katze.boot.plugins.redis.RedisTemplateManager;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Collection;
import java.util.List;
import java.util.function.Function;

/**
 * 说  明：Redis 对Key-List操作的封装
 * 作  者：zf.zeng
 * 日  期：2021-02-15 (星期一)
 **/
public class RedisListOperations<V>{

    private final ListOperations<String, V> listOperations;
    private RedisTemplateManager<V> manager;

    public RedisListOperations(RedisTemplate<String, V> redisTemplate){
        this.listOperations = redisTemplate.opsForList();
    }

    public RedisListOperations(RedisTemplateManager<V> manager){
        this.manager = manager;
        this.listOperations = manager.primary().opsForList();
    }

    public <R>R select(int database, Function<ListOperations<String, V>, R> function){
        return function.apply(database < 0? this.listOperations:this.manager.select(database).opsForList());
    }

    /**
     * 根据下标获取值
     * @param key 键
     * @param index 下标
     * @return 指定下标的值
     */
    public V index(String key, long index){
        return this.listOperations.index(key, index);
    }

    /**
     * 获取列表指定范围内的所有值
     * @param key 键
     * @param start 开始下标
     * @param end 结束下标
     * @return 指定范围内全部值
     */
    public List<V> range(String key, long start, long end){
        return this.listOperations.range(key, start, end);
    }

    /**
     *  移除集合中的左边第一个元素
     * 如果列表没有元素,会堵塞到列表一直有元素或者超时为止
     * @param key 键
     * @return 移除的值
     */
    public V leftPop(String key){
        return this.listOperations.leftPop(key);
    }

    /**
     * 移除集合中右边的第一个元素
     * 如果列表没有元素,会堵塞到列表一直有元素或者超时为止
     * @param key 键
     * @return 移除的值
     */
    public V rightPop(String key){
        return this.listOperations.rightPop(key);
    }

    /**
     * 向集合最左边添加元素
     * @param key 键
     * @return 当前队列的长度
     */
    public Long leftPush(String key, V value){
        return this.listOperations.leftPush(key, value);
    }

    /**
     * 向集合最左边批量添加元素
     * 导入顺序按照 Collection 顺序
     * 如: a b c => c b a
     * @param key 键
     * @param values 值
     * @return 当前队列的长度
     */
    public Long leftPushAll(String key, Collection<V> values){
        return this.listOperations.leftPushAll(key, values);
    }

    /**
     * 向集合最右边添加元素
     * @param key 键
     * @return 当前队列的长度
     */
    public Long rightPush(String key, V value){
        return this.listOperations.rightPush(key, value);
    }

    /**
     * 向集合最右边批量添加元素
     * 导入顺序按照 Collection 顺序
     * 如: a b c => a b c
     * @param key 键
     * @param values 值
     * @return 当前队列的长度
     */
    public Long rightPushAll(String key, Collection<V> values){
        return this.listOperations.rightPushAll(key, values);
    }

    /**
     * 移除集合中右边的元素，同时在左边加入一个元素
     * @param sourceKey 右出栈的列表
     * @param destinationKey 左入栈的列表
     * @return 操作的值
     */
    public Object rightPopAndLeftPush(String sourceKey, String destinationKey){
        return this.listOperations.rightPopAndLeftPush(sourceKey, destinationKey);
    }

    /**
     * 从存储在键中的列表中删除等于值的元素
     * count> 0：删除等于从左到右移动的值的第一个元素；
     * count< 0：删除等于从右到左移动的值的第一个元素；
     * count = 0：删除等于value的所有元素。
     * @param key 键
     * @param count 个数
     * @param value 值
     * @return 成功删除的个数
     */
    public Long remove(String key, long count, V value){
        return this.listOperations.remove(key, count, value);
    }

    /**
     * 删除列表 [start,end] 以外的所有元素
     * @param key 键
     * @param start 开始下标
     * @param end 结束下标
     */
    public void trim(String key, long start, long end){
        this.listOperations.trim(key, start, end);
    }

    /**
     * 获取列表指定长度
     * @param key 键
     * @return 当前队列的长度
     */
    public Long size(String key){
        return this.listOperations.size(key);
    }
}
